﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InterfaceOperacion;
using System.Diagnostics;
using System.Reflection;

namespace Calculadora
{
    public class ServiciosPlugins
    {
        //Devuelve una Lista con los plugins en la carpeta %*Directorio del .exe*%/Plugins
        public ICollection<InterfacePlugin> actualizarPlugins()
        {

            ICollection<InterfacePlugin> todosPlugins = new List<InterfacePlugin>();

            //Busco en el directorio actual, en la carpeta Plugins, los archivos DLL.

            string path = Directory.GetCurrentDirectory();
            string carpeta = "Plugins";
            path = Path.Combine(path, carpeta);

            string[] nombresDLLs = null;
            if (Directory.Exists(path))
            {
                nombresDLLs = Directory.GetFiles(path, "*.dll");
            }

            //Una vez que tengo los nombres de los DLLs en esa carpeta, obtengo los archivos ensamblados.
            if(nombresDLLs!=null)
            {
                ICollection<Assembly> ensamblados = new List<Assembly>(nombresDLLs.Length);
                foreach (string dll in nombresDLLs)
                 {
                    AssemblyName nombre = AssemblyName.GetAssemblyName(dll);
                    Assembly ens = Assembly.Load(nombre);
                    ensamblados.Add(ens);
                 }

                /*Teniendo el arreglo con archivos ensamblados, puedo acceder a ellos y ver si contienen alguna clase que sea
                de la interfaz "InterfacePlugin".*/

                Type tipoPlugin = typeof(InterfacePlugin);
                ICollection<Type> tiposPlugins = new List<Type>(); 

                foreach (Assembly archivo in ensamblados)
                {
                    if (archivo != null)
                    {
                    //Recupero todas las clases que hay en ese archivo ensamblado
                    Type[] tiposArchivo = archivo.GetTypes(); 
                    //Recorro esos tipos para ver si coinciden con mi interfaz
                    foreach (Type tipo in tiposArchivo)
                      {
                        //Si la clase no es abstracta ni es interfaz, y además la interfaz de la clase es InterfacePlugin
                        if (!(tipo.IsAbstract || tipo.IsInterface) && (tipo.GetInterface(tipoPlugin.FullName) != null))
                        {
                            tiposPlugins.Add(tipo);
                        }
                      }
                    tiposArchivo = null;

                    }   
                }

                //Por último, al tener los tipos de los plugins, creo instancias de los mismos a través de Activator
                foreach (Type tipo in tiposPlugins)
                {
                  InterfacePlugin plug = (InterfacePlugin)Activator.CreateInstance(tipo);
                  todosPlugins.Add(plug);
                  plug = null;
                 }
                tiposPlugins.Clear();
           }
            
            nombresDLLs = null;
            return todosPlugins;
        
        }

    }
}
